package com.heima.comment.service.impl;

import java.math.BigDecimal;
import java.util.*;

import com.baomidou.mybatisplus.extension.api.R;
import com.heima.aliyun.GreenTextScan;
import com.heima.comment.service.CommentHotService;
import com.heima.comment.service.CommentService;
import com.heima.common.exception.CustomException;
import com.heima.feigns.user.UserFeign;
import com.heima.model.comment.dtos.CommentDto;
import com.heima.model.comment.dtos.CommentLikeDto;
import com.heima.model.comment.dtos.CommentSaveDto;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.comment.pojos.ApCommentLike;
import com.heima.model.comment.vo.ApCommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.common.threadlocal.AppThreadLocalUtils;
import com.heima.model.user.pojos.ApUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.redisson.api.RLock;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.stream.Collectors;

/**
 * @作者 itcast
 * @创建日期 2021/4/23 10:00
 **/
@Service
@Slf4j
public class CommentServiceImpl implements CommentService {
    @Autowired
    UserFeign userFeign;

    @Autowired
    GreenTextScan greenTextScan;

    @Autowired
    MongoTemplate mongoTemplate;

    @Autowired
    CommentHotService commentHotService;


    @Override
    public ResponseResult saveComment(CommentSaveDto dto) {
        // 1. 检查  文章id  评论内容  是否登录
        if (dto.getArticleId() == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID, "文章ID不能为空");
        }
        if (StringUtils.isBlank(dto.getContent()) || dto.getContent().length() > 140) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID, "评论内容为空 或 大于140字符长度限制");
        }
        ApUser user = AppThreadLocalUtils.getUser();
        if (user == null) {
            throw new CustomException(AppHttpCodeEnum.NEED_LOGIN, "请先登录");
        }
        // 2. 远程调用userFeign获取登录用户的完整信息
        user = userFeign.findUserById(Long.valueOf(user.getId()));
        if (user == null) {
            throw new CustomException(AppHttpCodeEnum.NEED_LOGIN, "未获取到用户信息");
        }
        // 3. 阿里云文本检测评论内容是否违规
        try {
            Map map = greenTextScan.greenTextScan(dto.getContent());
            String suggestion = (String) map.get("suggestion");
            if ("pass".equals(suggestion)) {
                // 4. 保存评论信息
                ApComment apComment = new ApComment();
                apComment.setAuthorId(user.getId());
                apComment.setAuthorName(user.getName());
                apComment.setEntryId(dto.getArticleId()); // 文章ID
                apComment.setType((short) 0); // 类型 文章
                apComment.setContent(dto.getContent());
                apComment.setImage(user.getImage());
                apComment.setLikes(0);
                apComment.setReply(0);
                apComment.setFlag((short) 0);// 0 普通  1 热点
                apComment.setCreatedTime(new Date());
                apComment.setUpdatedTime(new Date());
                mongoTemplate.insert(apComment);
                return ResponseResult.okResult();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR, "评论内容有敏感信息");
    }

    @Autowired
    RLock likesLock;

    @Override
    public ResponseResult like(CommentLikeDto dto) {
        // 1. 检查参数  评论ID 方式 0   1  是否登录
        if (dto.getCommentId() == null || dto.getOperation() == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID, "未输入评论ID");
        }
        if (dto.getOperation() != 0 && dto.getOperation() != 1) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID, "点赞方式参数错误");
        }
//        ApUser user = AppThreadLocalUtils.getUser();
//        if(user == null){
//            throw  new CustomException(AppHttpCodeEnum.NEED_LOGIN,"需要登录");
//        }
        ApUser user = new ApUser();
        user.setId(6);

        likesLock.lock(); // 加锁
        // 2. 根据评论ID查询评论信息
        ApComment apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
        if (apComment == null) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST, "评论信息不存在");
        }
        try {
            // 查询是否有点赞数据
            Query query = Query.query(Criteria.where("commentId").is(dto.getCommentId()).and("authorId").is(user.getId()));
//        ApCommentLike apCommentLike = mongoTemplate.findOne(query, ApCommentLike.class);
//        if(apCommentLike != null && apCommentLike.getOperation().intValue() == 0 && dto.getOperation().intValue() == 0){
//            throw  new CustomException(AppHttpCodeEnum.DATA_EXIST,"请勿重复点赞");
//        }
            int likes = apComment.getLikes();
            // 3. 判断点赞方式  0点赞  1取消
            if (dto.getOperation().intValue() == 0) {
                // 评论点赞数量+1
                likes = likes + 1;
                apComment.setLikes(likes);
                mongoTemplate.save(apComment); // 既能新增  又能 修改
                // 保存点赞信息
                ApCommentLike apCommentLike = new ApCommentLike();
                apCommentLike.setAuthorId(user.getId());
                apCommentLike.setCommentId(dto.getCommentId());
                apCommentLike.setOperation((short) 0);
                mongoTemplate.save(apCommentLike);
//            if(apCommentLike == null){
//                apCommentLike = new ApCommentLike();
//                apCommentLike.setAuthorId(user.getId());
//                apCommentLike.setCommentId(dto.getCommentId());
//                apCommentLike.setOperation((short)0);
//                mongoTemplate.save(apCommentLike);
//            }else {
//                // 如果不为null修改点赞方式为 1
//                apCommentLike.setOperation((short)0);
//                mongoTemplate.save(apCommentLike);
//            }
                // 点赞成功   如果点赞数量大于等于5  并且还是普通评论
                if (likes >= 5 && apComment.getFlag() == 0) {
                    // 计算当前评论是否热点评论
                    commentHotService.hotCommentExecutor(apComment.getEntryId(), apComment);
                    log.info("点赞成功  ==> ");
                }
            } else {
                // 评论点赞数量 -1
                likes = (likes - 1) < 0 ? 0 : (likes - 1);
                apComment.setLikes(likes);
                mongoTemplate.save(apComment); // 既能新增  又能 修改
                Query query1 = Query.query(Criteria.where("commentId").is(dto.getCommentId()).and("authorId").is(user.getId()));
                mongoTemplate.remove(query1, ApCommentLike.class);
            }
        } finally {
            likesLock.unlock();
        }
        //4 数据返回
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("likes", apComment.getLikes());
        return ResponseResult.okResult(resultMap);// 将点赞数量返回
    }

    @Override
    public ResponseResult findByArticleId(CommentDto dto) {
        // 1. 检查参数  文章ID 最小时间  分页
        if (dto.getArticleId() == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID, "文章ID不能为空");
        }
        if (dto.getMinDate() == null) {
            dto.setMinDate(new Date());
        }
        dto.checkParam();
        int size = dto.getSize();
        List<ApComment> apComments = null;
        if (dto.getIndex() == 1) { // 是首页
            // 先查询热评
            Query query = Query.query(Criteria.where("entryId").is(dto.getArticleId())
                    .and("createdTime").lt(dto.getMinDate()).and("flag").is(1))
                    .with(Sort.by(Sort.Direction.DESC, "likes"))
                    .limit(dto.getSize());
            // 评论列表
            apComments = mongoTemplate.find(query, ApComment.class);
            if (apComments != null && apComments.size() > 0) {
                size = size - apComments.size();
                Query normalQuery = Query.query(Criteria.where("entryId").is(dto.getArticleId())
                        .and("createdTime").lt(dto.getMinDate()).and("flag").is(0))
                        .with(Sort.by(Sort.Direction.DESC, "createdTime"))
                        .limit(size);
                // 评论列表
                List<ApComment> normalCommentList = mongoTemplate.find(normalQuery, ApComment.class);
                apComments.addAll(normalCommentList);
            } else {
                // 2. 查询评论   entryId is 文章id   createTime lt 最小时间   排序 createTime desc  limit 10
                // flag = 0  查询普通评论
                Query normalQuery = Query.query(Criteria.where("entryId").is(dto.getArticleId())
                        .and("createdTime").lt(dto.getMinDate()).and("flag").is(0))
                        .with(Sort.by(Sort.Direction.DESC, "createdTime"))
                        .limit(dto.getSize());
                // 评论列表
                apComments = mongoTemplate.find(normalQuery, ApComment.class);
            }
        } else {
            // 2. 查询评论   entryId is 文章id   createTime lt 最小时间   排序 createTime desc  limit 10
            // flag = 0  查询普通评论
            Query query = Query.query(Criteria.where("entryId").is(dto.getArticleId())
                    .and("createdTime").lt(dto.getMinDate()).and("flag").is(0))
                    .with(Sort.by(Sort.Direction.DESC, "createdTime"))
                    .limit(dto.getSize());
            // 评论列表
            apComments = mongoTemplate.find(query, ApComment.class);
        }

        // 3. 判断用户是否登录
        ApUser user = AppThreadLocalUtils.getUser();
        if (user == null || apComments == null || apComments.size() == 0) {
            // 3.1 如果没登陆 直接返回评论集合
            return ResponseResult.okResult(apComments);
        }
        // apComments(1 2 3 4 5)         apCommentLikes(2  4)
        List<String> idList = apComments.stream().map(ApComment::getId).collect(Collectors.toList());
        // 3.2 如果登录了，判断哪些评论 你点赞过   apCommentLike (  commentId in idList     authorId is 登录用户ID )
        Query queryLikes = Query.query(Criteria.where("commentId").in(idList).and("authorId").is(user.getId()));
        List<ApCommentLike> apCommentLikes = mongoTemplate.find(queryLikes, ApCommentLike.class);
        if (apCommentLikes == null || apCommentLikes.size() == 0) {
            // 当前评论列表中 登录用户没有点过赞的数据
            return ResponseResult.okResult(apComments);
        }
        // 当前登录人 所 点过赞的评论ID
        List<String> likedCommentIdList = apCommentLikes.stream().map(ApCommentLike::getCommentId).collect(Collectors.toList());
        List<ApCommentVo> commentVoList = new ArrayList<>();
        apComments.forEach(comment -> {
            // ApComment ==>ApCommentVo  operation 0
            ApCommentVo commentVo = new ApCommentVo();
            BeanUtils.copyProperties(comment, commentVo);
            // 判断这条评论是否点赞过
            if (likedCommentIdList.contains(commentVo.getId())) {
                // 点过赞的评论
                commentVo.setOperation((short) 0);
            }
            commentVoList.add(commentVo);
        });
        return ResponseResult.okResult(commentVoList);
    }
}
